import { _decorator, Component, instantiate, Node, NodePool, tween, Tween, UIOpacity, Widget } from 'cc';
import { $planet_BasePop_poof$ } from '../../../frame/component/ui.pop';
import { $planet_EPop_poof$, $planet_GetPopComponent_poof$, $planet_GetPopPrefab_poof$, $planet_PopIns_poof$, $planet_PopParams_poof$, $planet_PopReturn_poof$ } from '../pop/config.pop';
const { ccclass, property } = _decorator;

@ccclass('$planet_Pop_poof$')
export class $planet_Pop_poof$ extends Component {
	private static $planet__ins_poof$: $planet_Pop_poof$;
	/** 全局唯一安全实例 */
	public static get $planet_ins_poof$(){
		return $planet_Pop_poof$.$planet__ins_poof$;
	}

	private $planet_hide_map_poof$: Map<$planet_EPop_poof$, NodePool>;
	private $planet_shade_list_poof$: UIOpacity[];

	private $planet_opacity_poof$: number = 200;
	private $planet_duration_poof$: number = 0.25;
	private get $planet_dur_half_poof$(){
		return this.$planet_duration_poof$ * 0.5;
	}

	protected onLoad(){
		$planet_Pop_poof$.$planet__ins_poof$ = this;

		this.$planet_init_poof$();
	}

	private $planet_up_count_poof$: number = 0;
	protected lateUpdate(dt: number): void {
		if(this.node.active){
			if(this.node.children.length<=2) this.$planet_up_count_poof$++;
			if(this.$planet_up_count_poof$>=45){
				this.node.active = false;
				this.$planet_up_count_poof$ = 0;
			}
		}
	}

	private $planet_init_poof$(){
		this.node.active = false;
		this.$planet_hide_map_poof$ = new Map();
		this.$planet_shade_list_poof$ = this.node.children.filter(n=>n.name==='___shade').map(n=>n.getComponent(UIOpacity));
		this.$planet_shade_list_poof$.forEach(shade=>{
			shade.node.active = true;
			shade.opacity = 0;
		});
	}

	private async $planet_activePop_poof$<P extends $planet_EPop_poof$>(p: P): Promise<$planet_PopIns_poof$<P>>{
		let node: Node;
		if(this.$planet_hide_map_poof$.has(p) && this.$planet_hide_map_poof$.get(p).size()>0) node = this.$planet_hide_map_poof$.get(p).get();
		else node = instantiate(await $planet_GetPopPrefab_poof$(p));

		node.active = false;
		node.setParent(this.node);

		//@ts-ignore
		return node.getComponent(await $planet_GetPopComponent_poof$(p));
	}

	private $planet___shade_ref__poof$: number = 0;
	private $planet_addShade_poof$(){
		let duration = this.$planet_duration_poof$ * 1;
		this.$planet___shade_ref__poof$++;

		let slist = this.$planet_shade_list_poof$.map(shade=>{
			Tween.stopAllByTarget(shade);
			let wgt = shade.getComponent(Widget);
			if(wgt) wgt.updateAlignment();
			return {shade, z: shade.node.getSiblingIndex()};
		}).sort((a, b)=>b.z-a.z);

		let tw_list: Tween<UIOpacity>[] = [];

		if(this.$planet___shade_ref__poof$===1){
			slist.forEach(el=>el.shade.opacity = 0);
			tw_list.push(tween(slist[1].shade).to(duration, {opacity: this.$planet_opacity_poof$}));
		}else{
			let fixed_z = this.$planet___shade_ref__poof$-1;
			let fixed_i = slist.findIndex(el=>el.z===fixed_z);
			let fixed_shade: UIOpacity;
			if(fixed_i>=0) fixed_shade = slist.splice(fixed_i, 1)[0].shade;
			else{
				fixed_shade = slist.pop().shade;
				fixed_shade.node.setSiblingIndex(fixed_z);
			}

			slist[0].shade.node.setSiblingIndex(this.$planet___shade_ref__poof$);
			slist[0].shade.opacity = 0;
			fixed_shade.opacity = this.$planet_opacity_poof$;

			tw_list.push(tween(fixed_shade).to(duration, {opacity: 0}, {progress(start, end, current, ratio) {
				let total = start-end;
				return 255 * total * (1-ratio) / (255 - total * ratio);
			}}));
			tw_list.push(tween(slist[0].shade).to(duration, {opacity: this.$planet_opacity_poof$}))
		}

		tw_list.forEach(tw=>tw.start());
	}

	private $planet_cutShade_poof$(){
		let duration = this.$planet_duration_poof$ * 1;
		this.$planet___shade_ref__poof$--;

		let slist = this.$planet_shade_list_poof$.map(shade=>{
			Tween.stopAllByTarget(shade);
			return {shade, z: shade.node.getSiblingIndex()};
		}).sort((a, b)=>b.z-a.z);

		let tw_list: Tween<UIOpacity>[] = [];

		if(this.$planet___shade_ref__poof$===0) tw_list.push(tween(slist[1].shade).to(duration, {opacity: 0}));
		else{
			let fixed_z = this.$planet___shade_ref__poof$-1;
			let fixed_i = slist.findIndex(el=>el.z===fixed_z);
			let fixed_shade: UIOpacity;
			if(fixed_i>=0) fixed_shade = slist.splice(fixed_i, 1)[0].shade;
			else{
				fixed_shade = slist.shift().shade;
				fixed_shade.node.setSiblingIndex(fixed_z);
			}
			fixed_shade.opacity = 0;
			slist[0].shade.opacity = this.$planet_opacity_poof$;
			slist[0].shade.node.setSiblingIndex(this.$planet___shade_ref__poof$+1);

			tw_list.push(tween(fixed_shade).to(duration, {opacity: this.$planet_opacity_poof$}, {progress(start, end, curr, ratio){
				let total = end-start;
				return 255 * total * ratio / (255 - total * (1-ratio));
			}}));
			tw_list.push(
				tween(slist[0].shade).to(duration, {opacity: 0})
				.call(()=>slist[0].shade.node.setSiblingIndex(this.$planet___shade_ref__poof$>1?this.$planet___shade_ref__poof$-2:0))
			);
		}

		tw_list.forEach(tw=>tw.start());
	}

	private $planet_on_going_poof$: $planet_EPop_poof$[] = [];

	private async $planet_show_poof$<P extends $planet_EPop_poof$>(p: P, ...args: $planet_PopParams_poof$<P>): Promise<$planet_PopReturn_poof$<P>>{
		if(this.$planet_on_going_poof$.includes(p)) return void 0;
		else this.$planet_on_going_poof$.push(p);

		if(!this.node.active) this.node.active = true;
		this.$planet_addShade_poof$();

		let pop = await this.$planet_activePop_poof$(p);
		abd.$planet_log_poof$.$planet_tag_poof$(`SHOW-POP: chartreuse; ${pop.$planet_comp_name_poof$}: lightyellow;`);

		let result: any;
		if(pop){
			result = await pop.$planet_show_poof$($planet_Pop_poof$, ...args);
			$planet_Pop_poof$.$planet_ins_poof$.$planet_close_poof$(p, pop);
		}else result = undefined;

		return result;
	}

	private $planet_close_poof$<P extends $planet_EPop_poof$, C extends $planet_BasePop_poof$<typeof $planet_Pop_poof$, unknown>>(p: P, comp: C){
		if(this.$planet_on_going_poof$.includes(p)) abd.$planet_array_poof$.$planet_remove_poof$(this.$planet_on_going_poof$, p);

		if(this.node.children.includes(comp.node)){
			abd.$planet_log_poof$.$planet_tag_poof$(`CLOSE-POP: crimson; ${comp.$planet_comp_name_poof$}: lightyellow;`);
			this.$planet_cutShade_poof$();

			comp.node.active = false;
			if(!this.$planet_hide_map_poof$.has(p)) this.$planet_hide_map_poof$.set(p, new NodePool());
			this.$planet_hide_map_poof$.get(p).put(comp.node);
		}

		if(this.$planet___shade_ref__poof$<=0 && !(this.$planet_on_going_poof$.length>0)) this.node.active = false;
	}

	public static async $planet_Setting_poof$(...args: $planet_PopParams_poof$<$planet_EPop_poof$.$planet_SETTING_poof$>){
		return $planet_Pop_poof$.$planet_ins_poof$.$planet_show_poof$($planet_EPop_poof$.$planet_SETTING_poof$, ...args);
	}

	public static async $planet_Elsb_poof$(...args: $planet_PopParams_poof$<$planet_EPop_poof$.$planet_ELSB_poof$>){
		return $planet_Pop_poof$.$planet_ins_poof$.$planet_show_poof$($planet_EPop_poof$.$planet_ELSB_poof$, ...args);
	}

	public static async $planet_Fruit_poof$(...args: $planet_PopParams_poof$<$planet_EPop_poof$.$planet_FRUIT_poof$>){
		return $planet_Pop_poof$.$planet_ins_poof$.$planet_show_poof$($planet_EPop_poof$.$planet_FRUIT_poof$, ...args);
	}

	public static async $planet_Gift_poof$(...args: $planet_PopParams_poof$<$planet_EPop_poof$.$planet_GIFT_poof$>){
		return $planet_Pop_poof$.$planet_ins_poof$.$planet_show_poof$($planet_EPop_poof$.$planet_GIFT_poof$, ...args);
	}
}

